/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package domein;

import domein.Message;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Lucas
 */
public class Server
{
    private int port;
    private boolean running;
    private ArrayList<ConnectionThread> list;

    public Server(int p)
    {
        this.port = p;
        list = new ArrayList<ConnectionThread>();
    }

    public void build()
    {
        running = true;
        try {

            ServerSocket s = new ServerSocket(port);
            System.out.println("Waiting for connections");
            while (running) {
                Socket so = s.accept();


                ConnectionThread t = new ConnectionThread(so);
                System.out.println(t.getUser() + " just connected");
                list.add(t);
                t.run();
            }
        }
        catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public synchronized void sendToAll(String message)
    {
        SimpleDateFormat date = new SimpleDateFormat();
        String time = date.format(new Date());

        String msg = "["+ time + "] " + message;


        for (ConnectionThread s : list) {
            if(s.isRunning())
                s.write(msg);

        }
        this.disposeDisconnectedThreads();
    }
    
    public synchronized void disposeDisconnectedThreads(){
        Iterator<ConnectionThread> it = list.iterator();

        while (it.hasNext()) {
            ConnectionThread current = it.next();

            if (!current.isRunning()) {
                list.remove(current);
            }
        }
    } 

    public void stop()
    {
        running = false;
    }

    public void remove(int id)
    {
        Iterator<ConnectionThread> it = list.iterator();

        while (it.hasNext()) {
            ConnectionThread current = it.next();

            if (current.getId() == id) {
                
                list.remove(current);
            }
        }
    }

    class ConnectionThread implements Runnable
    {
        private Socket s;
        private ObjectOutputStream output;
        private ObjectInputStream input;
        private int id;
        private boolean running;
        private String user;

        public ConnectionThread(Socket s)
        {
            this.s = s;
            id = id++;
            try {
                running = true;
                output = new ObjectOutputStream(s.getOutputStream());
                input = new ObjectInputStream(s.getInputStream());

                user = (String) input.readObject();

                System.out.println(new Date().toString() + " : " + user + " is connected");


            }
            catch (IOException ex) {
                Logger.getLogger(ConnectionThread.class.getName()).log(Level.SEVERE, null, ex);
            }
            catch (ClassNotFoundException e) {
                System.err.println(e);
                System.exit(1);
            }
            
        }

        public String getUser()
        {
            return user;
        }

        public void setUser(String u)
        {
            this.user = u;
        }

        public void write(String msg)
        {
            if (s.isConnected()) {
                try {
                    output.writeObject(msg);
                }
                catch (IOException ex) {
                    Logger.getLogger(ConnectionThread.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        public void run()
        {

            running = true;

            while (running) {
                try {
                    String m = (String) input.readObject();
                    SimpleDateFormat format = new SimpleDateFormat();

                    //String message = m.getMessage();

//                    int type = m.getType();
//
//                    switch (type) {
//                        case 1:
//                            sendToAll(user + ':' + message);
//                            break;
//                        case 2:
//                            write(user + " logged out");
//                            running = false;
//                            break;
//                        case 0:
//                            write("Users logged in at " + format.format(new Date()));
//
//                            Iterator<ConnectionThread> it = list.iterator();
//
//                            while (it.hasNext()) {
//
//                                write(it.next().getUser() + "\n");
//                            }
//                            break;
//                    }

                }
                catch (IOException ex) {
                    //Logger.getLogger(ConnectionThread.class.getName()).log(Level.SEVERE, null, ex);
                    //close();
                    System.out.println("A user has disconnected");
                    //close();
                }
                catch (ClassNotFoundException ex) {
                    //Logger.getLogger(ConnectionThread.class.getName()).log(Level.SEVERE, null, ex);
                    //close();
                }
                catch (NullPointerException ex)
                {
                    System.out.println("STAHP");
                }
                finally
                {
                    running = false;
                    close();
                }
            }


        }

        public int getId()
        {
            return id;
        }

        public boolean isRunning()
        {
            return running;
        }
        
        public void close()
        {
            try {
                input.close();
                output.close();
                s.close();
            }
            catch (IOException ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
